package main

import (
	"net/http"
	"strconv"
	"time"

	"git.oschina.net/linyubin/ongoing"
	jwt "github.com/dgrijalva/jwt-go"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
)

var engine *ongoing.Engine

func main() {

	//init engine
	engine = ongoing.NewEngine()
	defer engine.Close()
	//init echo
	e := echo.New()

	e.Use(middleware.CORS())

	api := e.Group("/api")
	api.Use(middleware.JWT([]byte("takeaction")))

	api.GET("/getuser", getUser)
	api.GET("/getallusers", getAllUsers)

	api.GET("/getmission/:missionid", getMission)
	api.GET("/getmissions", getMissions)
	api.GET("/getallmissions", getAllMissions)
	api.POST("/addmission", addMission)
	api.POST("/delmission", delMission)
	api.POST("/finishmission", finishMission)
	api.POST("/delaymission", delayMission)

	//e.POST("/api/adduser", addUser)
	e.POST("/login", login)

	e.Logger.Fatal(e.Start("127.0.0.1:8080"))
}

func login(c echo.Context) error {
	username := c.FormValue("username")
	password := c.FormValue("password")

	if username == "" || password == "" {
		return c.JSON(http.StatusOK, errMessage("用户名或者密码为空"))
	}

	if engine.IsUserExist(username) {
		if engine.CheckUser(username, password) {
			t := getToken(username, password)
			if t == "" {
				return c.JSON(http.StatusOK, errMessage("获得Token错误"))
			}
			return c.JSON(http.StatusOK, sucMessage("获得Token正确", t))
		}
	} else {
		newuser := new(ongoing.User)
		newuser.Name = username
		newuser.Passwd = password
		err := engine.AddUser(newuser)
		if err != nil {
			return c.JSON(http.StatusOK, errMessage("注册失败"))
		}
		t := getToken(username, password)
		if t == "" {
			return c.JSON(http.StatusOK, errMessage("获得Token错误"))
		}
		return c.JSON(http.StatusOK, sucMessage("获得Token正确", t))
	}

	return c.JSON(http.StatusOK, errMessage("密码错误"))
}

func getUser(c echo.Context) error {

	u := c.Get("user").(*jwt.Token)
	claims := u.Claims.(jwt.MapClaims)
	uname := claims["username"].(string)

	user, err := engine.GetUserByName(uname)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage("查询错误"))
	}
	user.Passwd = ""

	return c.JSON(http.StatusOK, sucMessage("查询正确", user))
}

func getAllUsers(c echo.Context) error {
	users, err := engine.GetAllUsers()
	if err != nil {
		return c.JSON(http.StatusOK, errMessage("查询错误"))
	}

	return c.JSON(http.StatusOK, sucMessage("查询正确", users))
}

func getMission(c echo.Context) error {
	mid, err := strconv.Atoi(c.Param("missionid"))
	if err != nil {
		return c.JSON(http.StatusOK, errMessage("输入ID格式错误"))
	}

	mission, err := engine.GetMissionById(mid)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage("查询错误"))
	}

	return c.JSON(http.StatusOK, sucMessage("查询正确", mission))
}

func getMissions(c echo.Context) error {

	u := c.Get("user").(*jwt.Token)
	claims := u.Claims.(jwt.MapClaims)
	uname := claims["username"].(string)

	user, err := engine.GetUserByName(uname)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage("查询错误"))
	}

	missions, err := engine.GetMissionsByUserName(user.Name)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage("查询错误"))
	}

	return c.JSON(http.StatusOK, sucMessage("查询正确", missions))
}

func getAllMissions(c echo.Context) error {
	missions, err := engine.GetALLMissions()
	if err != nil {
		return c.JSON(http.StatusOK, errMessage("查询错误"))
	}

	return c.JSON(http.StatusOK, sucMessage("查询正确", missions))
}

func addMission(c echo.Context) error {
	mission := new(ongoing.Mission)
	if err := c.Bind(mission); err != nil {
		return c.JSON(http.StatusOK, errMessage("解析错误"))
	}

	if mission.Mission == "" || mission.Description == "" || mission.TimeLimit == "" {
		return c.JSON(http.StatusOK, errMessage("数据不全"))
	}

	u := c.Get("user").(*jwt.Token)
	claims := u.Claims.(jwt.MapClaims)
	uname := claims["username"].(string)

	user, err := engine.GetUserByName(uname)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage("查询错误"))
	}

	mission.UserName = user.Name

	err = engine.AddMission(mission)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage(err.Error()))
	}

	return c.JSON(http.StatusOK, sucMessage("任务添加正确", ""))
}

func delMission(c echo.Context) error {
	mission := new(ongoing.Mission)
	if err := c.Bind(mission); err != nil {
		return c.JSON(http.StatusOK, errMessage("解析错误"))
	}

	if mission.ID == 0 {
		return c.JSON(http.StatusOK, errMessage("数据不全"))
	}

	_, err := engine.GetMissionById(mission.ID)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage("任务不存在"))
	}

	err = engine.DelMission(mission.ID)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage(err.Error()))
	}

	return c.JSON(http.StatusOK, sucMessage("任务删除正确", ""))
}

func finishMission(c echo.Context) error {
	mission := new(ongoing.Mission)
	if err := c.Bind(mission); err != nil {
		return c.JSON(http.StatusOK, errMessage("解析错误"))
	}

	if mission.ID == 0 || mission.SelfComment == "" {
		return c.JSON(http.StatusOK, errMessage("数据不全"))
	}

	_, err := engine.GetMissionById(mission.ID)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage("任务不存在"))
	}

	err = engine.FinishMission(mission)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage(err.Error()))
	}

	return c.JSON(http.StatusOK, sucMessage("任务完成正确", ""))
}

func delayMission(c echo.Context) error {
	m := new(ongoing.Mission)
	if err := c.Bind(m); err != nil {
		return c.JSON(http.StatusOK, errMessage("解析错误"))
	}

	if m.ID == 0 || m.TimeLimit == "" || m.DelayReason == ""{
		return c.JSON(http.StatusOK, errMessage("数据不全"))
	}

	mission, err := engine.GetMissionById(m.ID)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage("任务不存在"))
	}

	if mission.Status == "已完成" {
		return c.JSON(http.StatusOK, errMessage("任务已完成"))
	}

	err = engine.DelayMission(m)
	if err != nil {
		return c.JSON(http.StatusOK, errMessage(err.Error()))
	}

	return c.JSON(http.StatusOK, sucMessage("任务延期正确", ""))
}

func errMessage(msg string) *ongoing.Message {
	return &ongoing.Message{Code: ongoing.C_ErrCode, Msg: msg}
}

func sucMessage(msg string, data interface{}) *ongoing.Message {
	return &ongoing.Message{Code: ongoing.C_SucCode, Msg: msg, Data: data}
}

func getToken(username, password string) string {
	// Create token
	token := jwt.New(jwt.SigningMethodHS256)

	// Set claims
	claims := token.Claims.(jwt.MapClaims)
	claims["username"] = username
	claims["password"] = password
	claims["exp"] = time.Now().Add(time.Hour * 24).Unix()

	// Generate encoded token and send it as response.
	t, err := token.SignedString([]byte("takeaction"))
	if err != nil {
		return ""
	}

	return t
}
